package com.gitee.sop.websiteserver.controller;

import com.alibaba.fastjson.JSONObject;
import com.gitee.fastmybatis.core.PageInfo;
import com.gitee.fastmybatis.core.query.Query;
import com.gitee.sop.websiteserver.bean.*;
import com.gitee.sop.websiteserver.controller.param.*;
import com.gitee.sop.websiteserver.controller.result.*;
import com.gitee.sop.websiteserver.entity.IspResource;
import com.gitee.sop.websiteserver.entity.IsvInfo;
import com.gitee.sop.websiteserver.entity.IsvKeys;
import com.gitee.sop.websiteserver.entity.UserAccount;
import com.gitee.sop.websiteserver.manager.DocManager;
import com.gitee.sop.websiteserver.mapper.IspResourceMapper;
import com.gitee.sop.websiteserver.mapper.PermIsvRoleMapper;
import com.gitee.sop.websiteserver.mapper.PermRolePermissionMapper;
import com.gitee.sop.websiteserver.service.FileConfigHandler;
import com.gitee.sop.websiteserver.service.SendCodeHandler;
import com.gitee.sop.websiteserver.service.UserService;
import com.gitee.sop.websiteserver.util.GenerateUtil;
import com.gitee.sop.websiteserver.vo.IsvInfoVo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author admin
 */
@RestController
@RequestMapping("portal/isv")
public class IsvController {

    @Autowired
    private UserService userService;

    @Autowired
    DocManager docManager;

    @Resource
    IspResourceMapper ispResourceMapper;

    @Resource
    PermRolePermissionMapper permRolePermissionMapper;

    @Resource
    private PermIsvRoleMapper permIsvRoleMapper;

    @Value("${api.url-test}")
    String urlTest;

    @Value("${api.url-prod}")
    String urlProd;

    @Value("${api.url-sandbox}")
    String gatewayUrl;

    @Resource
    private SendCodeHandler sendCodeHandler;

    @Resource
    private FileConfigHandler fileConfigHandler;

    @GetMapping("/getIsvList")
    public Result getIsvList(IsvPageParam pageParam) {
        LoginUser loginUser = UserContext.getLoginUser();
        PageInfo<IsvInfo> pageInfo = userService.getIsvInfoList(loginUser.getUserId(), pageParam);
        return Result.ok(pageInfo);
    }

    @GetMapping("/getIsvKeys")
    public Result getIsvKeysInfo(@RequestParam String appKey) {
        if (StringUtils.isBlank(appKey)) {
            return Result.err("应用ID不能为空");
        }
        IsvKeys isvKeys = userService.getIsvKeys(appKey);
        return Result.ok(isvKeys);
    }

    @GetMapping("/getPublicKeyIsv")
    public Result getPublicKeyIsv() throws Exception {
        RSATool rsaToolIsv = new RSATool(RSATool.KeyFormat.PKCS8, RSATool.KeyLength.LENGTH_2048);
        RSATool.KeyStore keyStoreIsv = rsaToolIsv.createKeys();
        Map<String, String> result = new HashMap<>();
        result.put("publicKeyIsv", keyStoreIsv.getPublicKey());
        result.put("privateKeyIsv", keyStoreIsv.getPrivateKey());
        return Result.ok(result);
    }

    @PostMapping("/resetPublicKeyIsv")
    public Result resetPublicKeyIsv(@RequestBody @Valid IsvPublicKeyUploadParam param) {
        String appKey = param.getAppKey();
        String publicKeyIsv = param.getPublicKeyIsv();
        String privateKeyIsv = param.getPrivateKeyIsv();
        IsvKeys isvKeys = userService.getIsvKeys(appKey);
        if (Objects.nonNull(isvKeys)) {
            isvKeys.setPublicKeyIsv(publicKeyIsv);
            isvKeys.setPrivateKeyIsv(privateKeyIsv);
            userService.updateIsvKey(isvKeys);

            IsvPublicKeyUploadResult isvPublicKeyUploadResult = new IsvPublicKeyUploadResult();
            isvPublicKeyUploadResult.setAppKey(appKey);
            isvPublicKeyUploadResult.setPublicKeyIsv(isvKeys.getPublicKeyIsv());
            isvPublicKeyUploadResult.setPublicKeyPlatform(isvKeys.getPublicKeyPlatform());
            userService.sendChannelMsg(appKey);
            return Result.ok(isvPublicKeyUploadResult);
        }

        return Result.err("操作失败");
    }

    @PostMapping("/createIsv")
    public Result addIsv(@RequestBody @Valid IsvInfoParam param) {
        LoginUser loginUser = UserContext.getLoginUser();
        userService.createIsv(loginUser.getUserId(), param.getRemark());
        return Result.ok();
    }

    @PostMapping("/updateIsv")
    public Result updateIsv(@RequestBody @Valid IsvInfoParam param) {
        byte status = param.isStatus() ? (byte) 1 : (byte) 2;
        userService.updateIsv(param.getId(), param.getRemark(), status);
        return Result.ok();
    }

    @Transactional(rollbackFor = Exception.class)
    @PostMapping("/deleteIsv")
    public Result deleteIsv(@RequestBody @Valid IsvInfoDeleteParam param) {
        if (StringUtils.isBlank(param.getAppKey())) {
            return Result.err("应用ID不能为空");
        }
        LoginUser loginUser = UserContext.getLoginUser();
        userService.deleteIsv(param.getAppKey(), loginUser.getUserId());
        return Result.ok();
    }

    @GetMapping("/getIsvInfo")
    public Result getIsvInfo(@RequestParam Long id) {
        IsvInfo isvInfo = userService.getIsvInfo(id);
        if (Objects.nonNull(isvInfo)) {
            IsvInfoVo isvInfoVo = new IsvInfoVo();
            isvInfoVo.setId(isvInfo.getId());
            isvInfoVo.setRemark(isvInfo.getRemark());
            isvInfoVo.setStatus(isvInfo.getStatus().intValue() == 1);
            return Result.ok(isvInfoVo);
        }
        return Result.err("信息不存在");
    }

    @GetMapping("/getIsvPortal")
    public Result getIsvPortal(@RequestParam String appKey) {
        IsvInfoResult isvInfoResult = new IsvInfoResult();
        JSONObject jsonObject = sendCodeHandler.initConfig(appKey);
        boolean hasMessage = Objects.nonNull(jsonObject);
        isvInfoResult.setMessageConfig(hasMessage);

        JSONObject fileConfig = fileConfigHandler.checkAndGetConfig(appKey);
        boolean hasFile = Objects.nonNull(fileConfig);
        isvInfoResult.setFileConfig(hasFile);
        return Result.ok(isvInfoResult);
    }

    //////////////

    /**
     * 修改密码
     *
     * @param param
     * @return
     */
    @PostMapping("/updatePassword")
    public Result updatePassword(@RequestBody @Valid UpdatePasswordParam param) {
        long userId = UserContext.getLoginUser().getUserId();
        UserAccount userAccount = userService.getUserAccountByUserId(userId);
        String oldPwdHex = GenerateUtil.getUserPassword(userAccount.getUsername(), param.getOldPassword());
        Validates.isTrue(!Objects.equals(oldPwdHex, userAccount.getPassword()), "旧密码错误");
        String newPwdHex = GenerateUtil.getUserPassword(userAccount.getUsername(), param.getPassword());
        userAccount.setPassword(newPwdHex);
        userService.updateUserAccount(userAccount);
        return Result.ok();
    }

    /**
     * 获取文档页菜单数据
     *
     * @return
     */
    @GetMapping("/getDocMenus")
    public Result getAllDoc(@RequestParam Long isvId) {
        //获取当前应用的权限
        List<String> roleCodes = permIsvRoleMapper.selectRoles(isvId);

        List<String> routeIdList = new ArrayList<>();
        Collection<DocInfo> docInfos = docManager.listAll();
        docInfos.forEach(docInfo -> {
            docInfo.getDocModuleList().forEach(docModule -> {
                docModule.getDocItems().forEach(docItem -> {
                    routeIdList.add(docItem.getName().concat(docItem.getVersion()));
                });
            });
        });

        if (routeIdList.size() > 0) {
            Map<String, List<RouteRoleDTO>> routeIdRoleMap = permRolePermissionMapper.listRouteRole(routeIdList)
                    .parallelStream()
                    .collect(Collectors.groupingBy(RouteRoleDTO::getRouteId));
            List<MenuProject> menuProjects = docInfos.stream()
                    .map(docInfo -> {
                        MenuProject menuProject = new MenuProject();
                        menuProject.setId(docInfo.getServiceId());
                        menuProject.setLabel(docInfo.getTitle());
                        // 构建模块
                        List<MenuModule> menuModules = docInfo.getDocModuleList()
                                .stream()
                                .map(docModule -> {
                                    MenuModule menuModule = new MenuModule();
                                    menuModule.setId(GenerateUtil.getUUID());
                                    menuModule.setLabel(docModule.getModule());
                                    // 构建文档
                                    List<MenuDocItem> docItems = docModule.getDocItems().stream()
                                            .map(docItem -> {
                                                MenuDocItem menuDocItem = new MenuDocItem();
                                                menuDocItem.setId(docItem.getId());
                                                menuDocItem.setLabel(docItem.getSummary());
                                                menuDocItem.setName(docItem.getName());
                                                menuDocItem.setVersion(docItem.getVersion());

                                                List<RouteRoleDTO> routeRoleDTOS = routeIdRoleMap.getOrDefault(docItem.getName().concat(docItem.getVersion()), Collections.emptyList());
                                                List<String> collect = routeRoleDTOS.stream().map(RouteRoleDTO::getRoleCode).collect(Collectors.toList());
                                                if (collect.contains("open") && roleCodes.contains("open")) {
                                                    menuDocItem.setOpen(true);
                                                } else {
                                                    menuDocItem.setOpen(false);
                                                    for (String code : collect) {
                                                        menuDocItem.setOpen(false);
                                                        if (roleCodes.contains(code)) {
                                                            menuDocItem.setOpen(true);
                                                        }
                                                    }
                                                }
                                                return menuDocItem;
                                            }).collect(Collectors.toList());
                                    menuModule.setChildren(docItems);
                                    return menuModule;
                                }).collect(Collectors.toList());
                        menuProject.setChildren(menuModules);
                        return menuProject;
                    }).collect(Collectors.toList());

            return Result.ok(menuProjects);
        }
        return Result.ok(Collections.EMPTY_LIST);
    }

    /**
     * 根据文档id查询文档内容
     *
     * @param id 文档id
     * @return
     */
    @GetMapping("/getDocItem")
    public Result<DocVO> getDocItem(String id) {
        DocVO docVO = new DocVO();
        LoginUser loginUser = UserContext.getLoginUser();
        docVO.setGatewayUrl(gatewayUrl);
        docVO.setAppId(loginUser.getAppKey());
        docVO.setUrlProd(urlProd);
        docVO.setUrlTest(urlTest);
        DocItem docItem = docManager.getDocItem(id);
        docVO.setDocItem(docItem);
        return Result.ok(docVO);
    }

    /**
     * 获取SDK列表
     *
     * @return
     */
    @GetMapping("listSdk")
    public Result<List<IspResource>> list() {
        List<IspResource> resourceList = ispResourceMapper.list(new Query());
        return Result.ok(resourceList);
    }
}
